﻿using Microsoft.AspNetCore.Http;
using System.Security.Claims;
using System.Security.Principal;

namespace Sage.FreeSqlManager.Tenant
{
    /// <summary>
    /// 租户中间件 - 负责从HTTP请求中提取租户信息并设置租户上下文
    /// </summary>
    /// <param name="next">请求处理管道中的下一个委托</param>
    /// <param name="options">租户中间件选项</param>
    public class TenantMiddleware(RequestDelegate next, TenantMiddlewareOptions options)
    {
        private readonly RequestDelegate _next = next ?? throw new ArgumentNullException(nameof(next));
        private readonly TenantMiddlewareOptions _options = options ?? throw new ArgumentNullException(nameof(options));

        /// <summary>
        /// 处理HTTP请求
        /// </summary>
        /// <param name="context">HTTP上下文</param>
        /// <returns>表示异步操作的任务</returns>
        public async Task InvokeAsync(HttpContext context)
        {
            ArgumentNullException.ThrowIfNull(context);

            try
            {
                long tenantId;

                // 优先使用自定义解析器（如果提供）
                if (_options.TenantIdResolver != null)
                {
                    tenantId = await _options.TenantIdResolver(context);

                    // 如果自定义解析器返回无效值且处于开发环境，则使用默认租户ID
                    if (tenantId <= 0 && _options.IsDevelopment)
                    {
                        tenantId = _options.DevDefaultTenantId;
                    }
                }
                else
                {
                    // 使用默认解析逻辑
                    tenantId = DefaultResolver(context);
                }

                if (tenantId > 0)
                {
                    TenantManager.Current = tenantId;
                }

                //Console.WriteLine($"Current.TenantID: {TenantManager.Current}");

                await _next(context);
            }
            catch (Exception ex)
            {
                // 记录异常，但不阻止异常继续传播
                Console.WriteLine($"租户中间件异常: {ex.Message}");
                // 只有在响应尚未开始时才重新抛出
                if (!context.Response.HasStarted)
                {
                    throw;
                }
                //throw;
            }
            finally
            {
                // 请求处理完成后清理租户上下文
                TenantManager.Current = 0;
            }
        }


        ///// <summary>
        ///// 从HTTP上下文中获取租户ID（默认解析逻辑）
        ///// </summary>
        ///// <param name="context">HTTP上下文</param>
        ///// <returns>租户ID，如果未找到则返回Guid.Empty，开发模式下返回默认租户ID</returns>
        //private Guid DefaultResolver(HttpContext context)
        //{
        //    // 开发环境：优先从查询字符串获取租户ID(便于测试)
        //    if (_options.IsDevelopment &&
        //        context.Request.Query.TryGetValue("tenant_id", out var queryTenant))
        //    {
        //        // 将查询字符串值解析为Guid
        //        if (Guid.TryParse(queryTenant.ToString(), out var queryTenantId) &&
        //            queryTenantId != Guid.Empty)
        //        {
        //            Console.WriteLine($"Request.Query:{queryTenantId}");
        //            return queryTenantId;
        //        }
        //    }

        //    // 方法1：从请求头中获取租户ID (API网关转发可能会用到这个)
        //    if (context.Request.Headers.TryGetValue("X-Tenant-ID", out var headerValues))
        //    {
        //        // 获取头部的第一个值并尝试解析为Guid
        //        string headerValue = headerValues.FirstOrDefault() ?? string.Empty;
        //        if (Guid.TryParse(headerValue, out var headerTenantId) &&
        //            headerTenantId != Guid.Empty)
        //        {
        //            Console.WriteLine($"Request.Headers:{headerTenantId}");
        //            return headerTenantId;
        //        }
        //    }

        //    // 方法2：从已认证用户的Claims中获取租户ID
        //    if (context.User.Identity is { IsAuthenticated: true })
        //    {
        //        Claim? tenantClaim = context.User.FindFirst("tenant_id");
        //        if (tenantClaim is not null &&
        //            Guid.TryParse(tenantClaim.Value, out var claimTenantId) &&
        //            claimTenantId != Guid.Empty)
        //        {
        //            Console.WriteLine($"User.Identity.Claim:{claimTenantId}");
        //            return claimTenantId;
        //        }
        //    }

        //    // 开发环境：返回默认租户ID
        //    if (_options.IsDevelopment)
        //    {
        //        Console.WriteLine($"开发环境当前租户:{_options.DevDefaultTenantId}");
        //        return _options.DevDefaultTenantId;
        //    }

        //    Console.WriteLine("Get TenantId Fail");
        //    // 未找到有效的租户ID，返回空Guid
        //    return Guid.Empty;
        //}

        /// <summary>
        /// 从HTTP上下文中获取租户ID（默认解析逻辑）
        /// </summary>
        /// <param name="context">HTTP上下文</param>
        /// <returns>租户ID，如果未找到则返回0，开发模式下返回默认租户ID</returns>
        private long DefaultResolver(HttpContext context)
        {
            // 开发环境：优先从查询字符串获取租户ID(便于测试)
            if (_options.IsDevelopment &&
                context.Request.Query.TryGetValue("tenant_id", out var queryTenant) &&
                int.TryParse(queryTenant, out var queryTenantId) &&
                queryTenantId > 0)
            {
                Console.WriteLine($"Request.Query:{queryTenantId}");
                return queryTenantId;
            }

            // 方法1：从请求头中获取 (api网关转发可能会用到这个)
            if (context.Request.Headers.TryGetValue("X-Tenant-ID", out var headerValue) &&
                int.TryParse(headerValue, out var headerTenantId) &&
                headerTenantId > 0)
            {
                Console.WriteLine($"Request.Headers:{headerTenantId}");
                return headerTenantId;
            }

            // 方法2：从已认证用户的Claims中获取
            IIdentity? identity = context.User.Identity;
            if (identity != null && identity.IsAuthenticated)
            {
                Claim? tenantClaim = context.User.FindFirst("tenant_id");
                if (tenantClaim != null &&
                    int.TryParse(tenantClaim.Value, out var claimTenantId) &&
                    claimTenantId > 0)
                {
                    Console.WriteLine($"User.Identity.Claim:{claimTenantId}");
                    return claimTenantId;
                }
            }

            // 开发环境：返回默认租户ID
            if (_options.IsDevelopment)
            {
                Console.WriteLine($"开发环境当前租户:{_options.DevDefaultTenantId}");
                return _options.DevDefaultTenantId;
            }

            Console.WriteLine($"Get TenantId Fail");
            // 未找到有效的租户ID
            return 0;
        }
    }
}